package com.ck.print.demo.jetty;

import lombok.extern.slf4j.Slf4j;
import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.annotations.*;
import org.eclipse.jetty.websocket.api.util.WSURI;
import org.eclipse.jetty.websocket.client.WebSocketClient;

import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

@Slf4j
public class EchoClient {
    public static void main(String[] args) throws Exception {
        URI uri = URI.create("ws://localhost:8182");

        if (args.length == 1)
            uri = WSURI.toWebsocket(new URI(args[0]));

        WebSocketClient client = new WebSocketClient();
        client.start();

        try {
            EchoClient.performEcho(client, uri);
        } finally {

        }
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                try {
                    client.stop();
                } catch (Exception e) {
                    log.warn("Failed to stop client", e);
                }
            }
        });
    }

    public static List<String> performEcho(WebSocketClient client, URI uri) throws IOException, ExecutionException, InterruptedException, TimeoutException {
        List<String> ret = new ArrayList<>();

        ClientEchoWebSocket clientEchoSocket = new ClientEchoWebSocket();
        Future<Session> fut = client.connect(clientEchoSocket, uri);
        Session session = fut.get(5, TimeUnit.SECONDS);
        session.sendText("ping", Callback.NOOP);

        String msg = clientEchoSocket.messageQueue.poll(5, TimeUnit.SECONDS);
        ret.add(msg);

//        session.close(StatusCode.NORMAL, "Goodbye", Callback.NOOP);
//        if (!clientEchoSocket.closeLatch.await(5, TimeUnit.SECONDS))
//            throw new IOException("Failed to receive WebSocket close");

        return ret;
    }

    @Slf4j
    @WebSocket
    public static class ClientEchoWebSocket {

        private final LinkedBlockingDeque<String> messageQueue = new LinkedBlockingDeque<>();
        private final CountDownLatch closeLatch = new CountDownLatch(1);

        @OnWebSocketClose
        public void onClose(int statusCode, String reason) {
            log.info("WebSocket Close: {} - {}", statusCode, reason);
            closeLatch.countDown();
        }

        @OnWebSocketOpen
        public void onOpen(Session session) {
            log.info("WebSocket Open: {}", session);
        }

        @OnWebSocketError
        public void onError(Throwable cause) {
            log.warn("WebSocket Error", cause);
        }

        @OnWebSocketMessage
        public void onText(String message) {
            log.info("Text Message [{}]", message);
            messageQueue.offer(message);
        }
    }
}
